package cn.jietuo.netty.chat;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author zhangx & jietuo_zx@163.com
 * @version 1.0
 * @date 2021/2/27
 * @description: 聊天服务器业务处理Handler
 */
public class ChatServerHandler extends SimpleChannelInboundHandler<String> {

    // 全局的时间执行器，是一个单例
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 有客户端连接上来
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 将该客户单上线的消息发送给其他客户端
        channelGroup.writeAndFlush("[客户端]" + channel.remoteAddress() + "上线了" + sdf.format(new Date()) + "\n");
        //将当前的客户端加入到channelGroup
        channelGroup.add(channel);
        System.out.println(channel.remoteAddress() + "上线了" + "\n");
    }

    /**
     * 客户端下线了
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 将该客户端下线的信息发送给其他客户端
        //先将此客户端移出channelGroup
        channelGroup.remove(channel);
        channelGroup.writeAndFlush("[客户端]" + channel.remoteAddress() + "下线了" + sdf.format(new Date()) + "\n");
        System.out.println(ctx.channel().remoteAddress() + " 下线了"+ "\n");
        System.out.println("channelGroup size=" + channelGroup.size());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        // 关闭通道
        ctx.close();
    }

    /**
     * 读取到数据
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel channel = ctx.channel();
        // 根据不同角色发送不同消息，如果是自己，前缀改为自己，是其他客户端，则显示消息来源
        channelGroup.forEach(ch -> {
            if (channel != ch){
                // 说明不是自己
                ch.writeAndFlush("[客户端]" + channel.remoteAddress() + "发送了消息：" + msg + "\n");
            }else{
                ch.writeAndFlush("[自己] 发送了消息：" + msg + "\n");
            }
        });
    }
}
